package com.laoxiang.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.laoxiang.execption.LxAdminException;
import com.laoxiang.modules.system.entity.*;
import com.laoxiang.modules.system.entity.dto.PageDTO;
import com.laoxiang.modules.system.entity.dto.SysUserDTO;
import com.laoxiang.modules.system.entity.vo.*;
import com.laoxiang.modules.system.mapper.*;
import com.laoxiang.modules.system.service.*;
import com.laoxiang.utils.AppHttpCodeEnum;
import com.laoxiang.utils.BeanCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;


import java.util.List;
import java.util.Objects;

/**
 * 系统用户表(SysUser)表服务实现类
 *
 * @author db
 * @since 2023-07-13 11:37:57
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysUserPostMapper sysUserPostMapper;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysPostService sysPostService;

    @Autowired
    private SysUserPostService sysUserPostService;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Override
    public PageDTO getUserList(Integer pageNum, Integer pageSize, SysUserVO sysUserVO) {
        // 构建查询条件(用户名、手机号、状态、创建时间)
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(sysUserVO.getUserName()),SysUser::getUserName,sysUserVO.getUserName());
        queryWrapper.eq(StringUtils.hasText(sysUserVO.getPhone()),SysUser::getPhone,sysUserVO.getPhone());
        queryWrapper.eq(Objects.nonNull(sysUserVO.getStatus()),SysUser::getStatus,sysUserVO.getStatus());
        queryWrapper.eq(Objects.nonNull(sysUserVO.getDeptId()),SysUser::getDeptId,sysUserVO.getDeptId());
        queryWrapper.orderByAsc(SysUser::getCreateTime);
        if(null != sysUserVO.getCreateTime() && null != sysUserVO.getUpdateTime()){
            queryWrapper.ge(SysUser::getCreateTime,sysUserVO.getCreateTime()).le(SysUser::getUpdateTime,sysUserVO.getUpdateTime());
        }

        if(Objects.isNull(pageNum)){
            pageNum = 1;
        }
        if(Objects.isNull(pageSize)){
            pageSize = 10;
        }

        Page<SysUser> sysUserPage = sysUserMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        List<SysUserDTO> sysUserDTOList = BeanCopyUtils.copyBeanList(sysUserPage.getRecords(), SysUserDTO.class);
        for(SysUserDTO sysUserDTO:sysUserDTOList){
            SysDept sysDept = sysDeptMapper.selectById(sysUserDTO.getDeptId());
            sysUserDTO.setDeptName(sysDept.getName());
        }
        // 封装pageDTO
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageIndex(pageNum);
        pageDTO.setPageSize(pageSize);
        pageDTO.setTotal(sysUserPage.getTotal());
        pageDTO.setRows(sysUserDTOList);

        return pageDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addUser(SysUser sysUser) {

        /**
         * 判断用户名是否唯一
         * 判断手机号是否唯一
         * 判断邮箱是否唯一
        */
        if(this.checkUserNameUnique(sysUser)> 0){
            throw new LxAdminException(AppHttpCodeEnum.USER_NAME_EXIST);
        }else if(!this.checkPhoneUnique(sysUser)){
            throw new LxAdminException(AppHttpCodeEnum.USER_PHONE_EXIST);
        }else if(!this.checkEmailUnique(sysUser)){
            throw new LxAdminException(AppHttpCodeEnum.USER_EMILE_EXIST);
        }

        // 后面引进spring Security之后进行密码加密处理
        // TODO

        int count = sysUserMapper.insert(sysUser);
        // 增加用户角色
        if(sysUser.getRoleIds()!=null&&sysUser.getRoleIds().length>0){
            insertUserRole(sysUser);
        }

        //增加用户岗位
        if(sysUser.getPostIds() != null && sysUser.getPostIds().length>0){
            insertUserPost(sysUser);
        }
        return count;
    }

    private void insertUserPost(SysUser sysUser) {
        Long[] postIds = sysUser.getPostIds();
        if(Objects.nonNull(postIds)){
            // TODO 后续修改成批量添加
            for(Long postId:postIds){
                SysUserPost sysUserPost = new SysUserPost();
                sysUserPost.setUserId(sysUser.getId());
                sysUserPost.setPostId(postId);
                sysUserPostMapper.insert(sysUserPost);
            }
        }
    }

    private void insertUserRole(SysUser sysUser) {
        Long[] roleIds = sysUser.getRoleIds();
        if(!Objects.isNull(roleIds)){
            // TODO 新增用户与角色管理(后续优化 批量添加)
            for(Long roleId:roleIds){
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setRoleId(roleId);
                sysUserRole.setUserId(sysUser.getId());
                sysUserRoleMapper.insert(sysUserRole);
            }
        }

    }

    @Override
    public UserInfoRolePostVO getUserById(Long userId) {

        // 获得用户修改要显示的信息
        SysUser sysUser = sysUserMapper.selectById(userId);
        UserInfoVO userInfoVO = BeanCopyUtils.copyBean(sysUser, UserInfoVO.class);

        // 获得所有角色信息
        List<SysRole> roleList = sysRoleService.getRoleList();
        // 获得所有岗位信息
        List<SysPost> postList = sysPostService.getPostList();


        // 获得该该用户的岗位id列表
        List<Long> postIds = sysUserPostService.getPostIdsByUserId(userId);

        // 获得该该用户的岗位id列表
        List<Long> roleIds = sysUserRoleService.getRoleIdsByUserId(userId);

        sysUser.setRoleIds(roleIds.toArray(new Long[roleIds.size()]));
        sysUser.setPostIds(postIds.toArray(new Long[postIds.size()]));

        UserInfoRolePostVO userInfoRolePostVO = new UserInfoRolePostVO();
        userInfoRolePostVO.setUserInfoVO(userInfoVO);
        userInfoRolePostVO.setRoles(roleList);
        userInfoRolePostVO.setPosts(postList);
        userInfoRolePostVO.setRoleIds(roleIds.toArray(new Long[roleIds.size()]));
        userInfoRolePostVO.setPostIds(postIds.toArray(new Long[postIds.size()]));


        return userInfoRolePostVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(SysUser sysUser) {

        // 先判断手机号、邮箱
        if(!checkPhoneUnique(sysUser)){
            throw new LxAdminException(AppHttpCodeEnum.USER_PHONE_EXIST);
        }else if (!checkEmailUnique(sysUser)){
            throw new LxAdminException(AppHttpCodeEnum.USER_EMILE_EXIST);
        }

        // 更新岗位（先删除，然后再插入）
        sysUserPostService.deleteUserPostByUserId(sysUser.getId());
        //增加用户岗位
        if(sysUser.getPostIds() != null && sysUser.getPostIds().length>0){
            insertUserPost(sysUser);
        }

        // 更新角色（先删除，然后再插入）
        sysUserRoleService.deleteUserRoleByUserId(sysUser.getId());
        if(sysUser.getRoleIds() != null && sysUser.getRoleIds().length>0){
            insertUserRole(sysUser);
        }

        // 更新用户信息
        sysUserMapper.updateById(sysUser);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long userId) {

        // 先删除用户角色信息
        sysUserRoleService.deleteUserRoleByUserId(userId);

        // 删除用户岗位信息
        sysUserPostService.deleteUserPostByUserId(userId);

        // 删除用户信息
        sysUserMapper.deleteById(userId);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bachDeleteUser(List<Long> ids) {
        if(!CollectionUtils.isEmpty(ids)){
            for(Long id:ids){
                // 先删除用户角色信息
                sysUserRoleService.deleteUserRoleByUserId(id);
                // 删除用户岗位信息
                sysUserPostService.deleteUserPostByUserId(id);
                // 删除用户信息
                sysUserMapper.deleteById(id);
            }
        }

    }

    @Override
    public int checkUserNameUnique(SysUser sysUser) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(sysUser.getUserName()),SysUser::getUserName,sysUser.getUserName());
        Integer count = sysUserMapper.selectCount(queryWrapper);
        return count;
    }

    @Override
    public boolean checkPhoneUnique(SysUser sysUser) {

        Long userId = Objects.isNull(sysUser.getId()) ? -1L : sysUser.getId();

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(sysUser.getPhone()),SysUser::getPhone,sysUser.getPhone());
        SysUser user = sysUserMapper.selectOne(queryWrapper);

        if (Objects.nonNull(user) && user.getId().longValue() != userId.longValue())
        {
            return false;
        }
        return true;
    }

    @Override
    public boolean checkEmailUnique(SysUser sysUser) {

        Long userId = Objects.isNull(sysUser.getId()) ? -1L : sysUser.getId();

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(sysUser.getEmail()),SysUser::getPhone,sysUser.getEmail());
        SysUser user = sysUserMapper.selectOne(queryWrapper);

        if (Objects.nonNull(user) && user.getId().longValue() != userId.longValue())
        {
            return false;
        }
        return true;
    }

    @Override
    public void updateUserStatus(UpdateUserStatusVO updateUserStatusVO) {
        SysUser sysUser = sysUserMapper.selectById(updateUserStatusVO.getId());
        sysUser.setStatus(updateUserStatusVO.getStatus());

        sysUserMapper.updateById(sysUser);
    }

    @Override
    public void restPassWord(RestPassWordVO restPassWordVO) {
        SysUser sysUser = sysUserMapper.selectById(restPassWordVO.getId());
        sysUser.setPassword(restPassWordVO.getPassword());

        sysUserMapper.updateById(sysUser);
    }

    @Override
    public void updatePassWord(UpdatePassWordVO updatePassWordVO) {
        // 先获得之前的密码
    }
}

